package com.smartstate.IOC.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.smartstate.IOC.dto.PageDTO;
import com.smartstate.IOC.entity.HalfHourPowerMeterSummary;
import com.smartstate.IOC.mapper.HalfHourPowerMeterSummaryMapper;
import com.smartstate.IOC.service.EquipmentService;
import com.smartstate.IOC.service.HalfHourPowerMeterSummaryService;
import com.smartstate.IOC.util.StringDateUtills;
import com.smartstate.IOC.vo.MoudelEquipmentVo;
import com.smartstate.IOC.vo.PowerMeterSummaryRec;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.groupingBy;

@Component
@Slf4j
public class HalfHourPowerMeterSummaryServiceImpl extends ServiceImpl<HalfHourPowerMeterSummaryMapper, HalfHourPowerMeterSummary> implements HalfHourPowerMeterSummaryService {

    @Autowired
    private EquipmentService equipmentService;

    @Override
    public Page<HalfHourPowerMeterSummary> queryAllPageByDTO(PageDTO pageDTO) {
        Page page = new Page(pageDTO.getPage(), pageDTO.getSize());
        QueryWrapper<HalfHourPowerMeterSummary> queryWrapper = new QueryWrapper<>();
        return baseMapper.selectPage(page, queryWrapper);
    }

    @Override
    public List<PowerMeterSummaryRec> getPowerMeterSummaryRecs(String startTime) {
        if (StringUtils.isBlank(startTime)) return Lists.newArrayList();
        String endTime = StringDateUtills.getDayStyleStrFromDateTime(new Date());
        List<PowerMeterSummaryRec> result = baseMapper.getPowerMeterSummaryRecs(startTime, endTime);
        if (CollectionUtils.isEmpty(result)) {
            return Lists.newArrayList();
        }
        result.stream().forEach(e ->{
            e.setSummaryEnergy(e.getSummaryEnergy().setScale(2, RoundingMode.CEILING));
            String dayPeriod = e.getDayPeriod().substring(8);
            if(dayPeriod.startsWith("0")){
                dayPeriod = e.getDayPeriod().substring(1);
            }
            e.setDayPeriod(dayPeriod);
        });
        return result;
    }

    public List<Map<String, Object>> getUnitPowers() {
        //获取园区楼栋模块数据树
        MoudelEquipmentVo rootMoudel = equipmentService.getMoudelEquipmentTree("1");
        if (rootMoudel == null || CollectionUtils.isEmpty(rootMoudel.getSubMoudels())) {
            log.info("=====getUnitPowers=====获取近单位电量抄表数据失败！无法获取楼栋模型。");
        }
        //获取朱模块树下的所有模块信息
        List<MoudelEquipmentVo> moudels = equipmentService.getTargetSubMoudels(rootMoudel);

        //获取目前所有要查询电表数据的楼层或楼栋的id，并查询db获取近三天内的电表数据
        List<String> moudelIds = moudels.stream().map(MoudelEquipmentVo::getMoudelId).collect(Collectors.toList());
        List<PowerMeterSummaryRec> powerPikRecs = baseMapper.getPeriodDeviceSummaryRecsByMoudelIds(null, null, moudelIds);
        Map<String, List<PowerMeterSummaryRec>> tempResult = powerPikRecs.stream().collect(groupingBy(PowerMeterSummaryRec::getObjId));


        List<Map<String, Object>> result = new ArrayList<>();
        for (MoudelEquipmentVo vo : moudels) {
            if (CollectionUtils.isNotEmpty(vo.getSubMoudels())) {
                continue;
            }
            List<PowerMeterSummaryRec> unitPickRecs = tempResult.get(vo.getMoudelId());
            if (CollectionUtils.isEmpty(unitPickRecs)) {
                continue;
            }
            Map<String, Object> innerResult = new HashMap<>();
            innerResult.put("moudelName", vo.getMoudelName());
            BigDecimal summValue = new BigDecimal(0);
            for (PowerMeterSummaryRec rec : unitPickRecs) {
                summValue = summValue.add(rec.getSummaryEnergy());
            }
            innerResult.put("total", summValue.setScale(2, RoundingMode.CEILING));
            result.add(innerResult);
        }
        return result;
    }

    @Override
    public List<Map<String, Object>> getRatioOnMonth() {
        MoudelEquipmentVo rootNode = equipmentService.getMoudelEquipmentTree("1");
        List<MoudelEquipmentVo> moudels = equipmentService.getTargetSubMoudels(rootNode);
        List<String> moudelIds = moudels.stream().map(MoudelEquipmentVo::getMoudelId).collect(Collectors.toList());

        //获取上月电表采集记录
        Calendar calendar = Calendar.getInstance();
//        calendar.set(Calendar.MONTH,calendar.get(Calendar.MONTH)-1);
        String endTime = StringDateUtills.getDayStyleStrFromDateTime(new Date(calendar.getTimeInMillis()));
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        String start = StringDateUtills.getDayStyleStrFromDateTime(new Date(calendar.getTimeInMillis()));
        List<PowerMeterSummaryRec> currMonthPickRecs = baseMapper.getPeriodDeviceSummaryRecsByMoudelIds(start, endTime, moudelIds);

        //获取上上个月电表采集记录
        Calendar lastCalendar = Calendar.getInstance();
        lastCalendar.set(Calendar.MONTH, lastCalendar.get(Calendar.MONTH) - 1);
        String LastEndTime = StringDateUtills.getDayStyleStrFromDateTime(new Date(lastCalendar.getTimeInMillis()));
        calendar.set(lastCalendar.DAY_OF_MONTH, 1);
        String LastStart = StringDateUtills.getDayStyleStrFromDateTime(new Date(lastCalendar.getTimeInMillis()));
        List<PowerMeterSummaryRec> lastMonthPickRecs = baseMapper.getPeriodDeviceSummaryRecsByMoudelIds(LastStart, LastEndTime, moudelIds);

        //<楼栋，<月份，电量>>
        List<Map<String, Object>> result = Lists.newArrayList();
        for (MoudelEquipmentVo moudelBuildings : rootNode.getSubMoudels()) {
            Map<String, Object> buildingMoudelInfos = new HashMap<>();
            List<MoudelEquipmentVo> buildingMoudels = equipmentService.getTargetSubMoudels(moudelBuildings);
            buildingMoudels = buildingMoudels.stream().filter(e -> StringUtils.isNotBlank(e.getDeviceId())).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(buildingMoudels)) {
                continue;
            }
            List<String> floorDevicies = buildingMoudels.stream().map(MoudelEquipmentVo::getMoudelId).collect(Collectors.toList());
            List<PowerMeterSummaryRec> currMothTempRecs = currMonthPickRecs.stream().filter(e -> floorDevicies.contains(e.getObjId())).collect(Collectors.toList());
            BigDecimal currMothSummValue = new BigDecimal(0);
            if (CollectionUtils.isNotEmpty(currMothTempRecs)) {
                for (PowerMeterSummaryRec tempRec : currMothTempRecs) {
                    currMothSummValue = currMothSummValue.add(tempRec.getSummaryEnergy());
                }
            }

            List<PowerMeterSummaryRec> lastMothTempRecs = lastMonthPickRecs.stream().filter(e -> floorDevicies.contains(e.getObjId())).collect(Collectors.toList());
            BigDecimal lastMothSummValue = new BigDecimal(0);
            if (CollectionUtils.isNotEmpty(lastMothTempRecs)) {
                for (PowerMeterSummaryRec tempRec : lastMothTempRecs) {
                    lastMothSummValue = lastMothSummValue.add(tempRec.getSummaryEnergy());
                }
            }
            buildingMoudelInfos.put("moudelName", moudelBuildings.getMoudelName());
            buildingMoudelInfos.put("lastMonthValues", currMothSummValue.setScale(2, RoundingMode.CEILING));
            BigDecimal value = new BigDecimal(0);
            if (!(currMothSummValue.doubleValue() == 0 && lastMothSummValue.doubleValue() == 0)) {
                if (lastMothSummValue.doubleValue() == 0) {
                    value = new BigDecimal(100);
                } else {
                    value = currMothSummValue.subtract(lastMothSummValue).divide(lastMothSummValue).setScale(2, RoundingMode.CEILING).multiply(new BigDecimal(100));
                }
            }

            buildingMoudelInfos.put("ratio", value);
            result.add(buildingMoudelInfos);
        }
        return result;
    }

    public static void main(String[] args) {
        BigDecimal value = new BigDecimal(0);
        System.out.println(value.doubleValue() == 0);
    }

    public Map<String, Map<String, BigDecimal>> getTotalPower() {
        //获取园区楼栋模块数据树
        MoudelEquipmentVo rootMoudel = equipmentService.getMoudelEquipmentTree("1");
        if (rootMoudel == null || CollectionUtils.isEmpty(rootMoudel.getSubMoudels())) {
            log.info("=====getTotalPower=====获取近三天电量抄表数据失败！无法获取楼栋模型。");
        }
        //获取朱模块树下的所有模块信息
        List<MoudelEquipmentVo> moudels = equipmentService.getTargetSubMoudels(rootMoudel);

        //获取目前所有要查询电表数据的楼层或楼栋的id，并查询db获取近三天内的电表数据
        List<String> moudelIds = moudels.stream().map(MoudelEquipmentVo::getMoudelId).collect(Collectors.toList());
        Calendar calendar = Calendar.getInstance();
        String endTime = StringDateUtills.getDayStyleStrFromDateTime(new Date(calendar.getTimeInMillis()));
        calendar.set(Calendar.DAY_OF_MONTH, calendar.get(Calendar.DAY_OF_MONTH) - 3);
        String start = StringDateUtills.getDayStyleStrFromDateTime(new Date(calendar.getTimeInMillis()));
        List<PowerMeterSummaryRec> powerPikRecs = baseMapper.getPeriodDeviceSummaryRecsByMoudelIds(start, endTime, moudelIds);

        List<String> dateStrs = powerPikRecs.stream().map(PowerMeterSummaryRec::getDayPeriod).distinct().collect(Collectors.toList());
        List<MoudelEquipmentVo> moudelInfos = rootMoudel.getSubMoudels();

        //构建进三日每栋用电数据  map<日期：map<楼号：用电量>>
        Map<String, Map<String, BigDecimal>> resutl = new HashMap<>();
        for (String dateStr : dateStrs) {
            Map<String, BigDecimal> moudelSummRecs = new HashMap<>();
            for (MoudelEquipmentVo moudelInfo : moudelInfos) {
                List<MoudelEquipmentVo> tempSubMoudles = equipmentService.getTargetSubMoudels(rootMoudel);
                List<String> subMoudelIds = tempSubMoudles.stream().map(MoudelEquipmentVo::getMoudelId).distinct().collect(Collectors.toList());
                List<PowerMeterSummaryRec> currModulePickRecs = powerPikRecs.stream().filter(e -> subMoudelIds.contains(e.getObjId())).collect(Collectors.toList());
                BigDecimal summValue = new BigDecimal(0);
                for (PowerMeterSummaryRec tempRec : currModulePickRecs) {
                    summValue = summValue.add(tempRec.getSummaryEnergy());
                }
                moudelSummRecs.put(moudelInfo.getMoudelName(), summValue.setScale(2, RoundingMode.CEILING));
            }
            resutl.put(dateStr, moudelSummRecs);
        }
        return resutl;
    }

    /**
     * 计算单位阶段内设备的用电总计
     *
     * @return
     */
    public Map<String, Map<String, BigDecimal>> getPeriodDeviceSummaryRecs() {
        Calendar calendar = Calendar.getInstance();
        String endTime = StringDateUtills.getDayStyleStrFromDateTime(new Date(calendar.getTimeInMillis()));
        calendar.set(Calendar.DAY_OF_MONTH, calendar.get(Calendar.DAY_OF_MONTH) - 3);
        String start = StringDateUtills.getDayStyleStrFromDateTime(new Date(calendar.getTimeInMillis()));

        MoudelEquipmentVo root = equipmentService.getMoudelEquipmentTree("3");
        Map<String, List<String>> moudelDeviceIds = new HashMap<>();
        for (MoudelEquipmentVo subMoudel : root.getSubMoudels()) {
            List<String> deviceIds = moudelDeviceIds.get(subMoudel.getMoudelName());
            if(CollectionUtils.isEmpty(deviceIds)){
                deviceIds = new ArrayList<>();
            }
            List<MoudelEquipmentVo> moudelEquipmentVos = equipmentService.getTargetSubMoudels(subMoudel);
            deviceIds.addAll(moudelEquipmentVos.stream().map(MoudelEquipmentVo :: getDeviceId).collect(Collectors.toList()));
            moudelDeviceIds.put(subMoudel.getMoudelName(), deviceIds);
        }

        //从db获取最近三天设备的用电数据
        List<PowerMeterSummaryRec> periodDeviceSummaryRecs = baseMapper.getPeriodDeviceSummaryRecs(start, endTime);
        //分组构造
        Map<String, List<PowerMeterSummaryRec>> tempDayMap = periodDeviceSummaryRecs.stream().collect(groupingBy(PowerMeterSummaryRec::getDayPeriod));

        Map<String, Map<String, BigDecimal>> resultMap = new HashMap<>();
        tempDayMap.entrySet().forEach(dayPeriodSumRec -> {
            Map<String, BigDecimal> innerMap = new HashMap<>();
            BigDecimal sumEnerge = new BigDecimal(0);
            for (Map.Entry<String, List<String>> moudelNameDeviceIds : moudelDeviceIds.entrySet()) {
                Double moudelSum = dayPeriodSumRec.getValue().stream().filter(e -> moudelNameDeviceIds.getValue().contains(e.getDeviceId())).collect(Collectors.summingDouble(e ->  Double.valueOf(e.getSummaryEnergy().doubleValue())));
                sumEnerge = sumEnerge.add(new BigDecimal(moudelSum));
                innerMap.put(moudelNameDeviceIds.getKey(), new BigDecimal(moudelSum).setScale(2, RoundingMode.CEILING));
            }
            innerMap.put("daySumarry", sumEnerge.setScale(2, RoundingMode.CEILING));
            resultMap.put(dayPeriodSumRec.getKey(), innerMap);
        });
        return resultMap;
    }



    @Override
    public List<Map<String, Float>> getElectricDataTotal() {
        ArrayList<Map<String, Float>> listMaps = new ArrayList<>();
        //获取当前年月
        Calendar calendar = Calendar.getInstance();
        //月份
        int month = calendar.get(Calendar.MONTH) + 1;
        String toMonth = String.valueOf(month);
        //年份
        int year = calendar.get(Calendar.YEAR);
        String toYear = String.valueOf(year);
        String date = String.join("-", toYear, toMonth);
        //要获取的六个月份
        List<String> sixMonth = getSixMonth(date);
        //六个月不需要包含当前月
        sixMonth.remove(date);
        //  根据月份查询每个月份的详细信息
        for (String s : sixMonth) {
            HashMap<String, Float> totalMap = new HashMap<>();
            //当前月的电量总数
            Float mouthData = baseMapper.getMouthData(s);
            if (mouthData == null) {
                Float aFloat = new Float(0.0);
                mouthData = aFloat;
            }
            //  当月和当月电量总数存入
            totalMap.put(s, mouthData);
            listMaps.add(totalMap);
        }
        return listMaps;
    }


    /**
     * * 获取某一月份的前六个月
     * * @param date 日期,格式:"2018-10"
     * * @return
     */
    public List<String> getSixMonth(String date) {
        //返回值
        List<String> list = new ArrayList<String>();
        int month = Integer.parseInt(date.substring(5, 7));
        int year = Integer.parseInt(date.substring(0, 4));
        for (int i = 6; i >= 0; i--) {
            if (month > 7) {
                if (month - i >= 10) {
                    list.add(year + "-" + String.valueOf(month - i));
                } else {
                    list.add(year + "-0" + String.valueOf(month - i));
                }
            } else {
                if (month - i <= 0) {
                    if (month - i + 12 >= 10) {
                        list.add(String.valueOf(year - 1) + "-" + String.valueOf(month - i + 12));
                    } else {
                        list.add(String.valueOf(year - 1) + "-0" + String.valueOf(month - i + 12));
                    }
                } else {
                    if (month - i >= 10) {
                        list.add(String.valueOf(year) + "-" + String.valueOf(month - i));
                    } else {
                        list.add(String.valueOf(year) + "-0" + String.valueOf(month - i));
                    }
                }
            }
        }
        return list;

    }


}
